#include"server.h"

server::server(string host ,int port,int nums,int max):redismanager(host,port),pool(nums),maxlisten(max)
{
    //套接在字
    this->listen_socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    
    //初始化addres
    this->address.sin_family=AF_INET;
    this->address.sin_addr.s_addr = INADDR_ANY;
    this->address.sin_port=htons(8888);

    //绑定监听套接字
    if(bind(listen_socket,(sockaddr*)&this->address,sizeof(this->address))==-1)
    {
        cerr<<"bind error"<<endl;
        return;
    }

    //监听套接字
    if(listen(listen_socket,this->maxlisten)==-1)
    {
        cerr<<"listen error"<<endl;
    }

    //实例化epoll
    for(int i=0;i<4;i++)
    {
        this->epoll_fds[i]=epoll_create1(0);
        if(this->epoll_fds[i]<0)
        {
            cerr<<"epoll_createl failed"<<endl;
            return ;
        }
    }

    //把每个epoll放入线程
    for(int i=0;i<4;i++)
    {
        this->pool.addtasks([this,temp=i](){
            this->start_epoll(this->epoll_fds[temp]);
        });
    }

    //接收新连接
    while(true)
    {
        this->newconnect();
    }
}

//分配fd
void server::organize_fd(int fd)
{
    struct epoll_event ev;
    ev.events=EPOLLIN|EPOLLET;
    ev.data.fd=fd;
    epoll_ctl(this->epoll_fds[this->time],EPOLL_CTL_ADD,fd,&ev);
    this->time++;
    if(this->time>=4)
    {
        this->time=0;
    }
}

//启动服务器
void server::start_epoll(int epollfd)
{
    struct epoll_event events[1000];
    while(true)
    {
        vector<string>need_handle_ccount;//记录需要发送的账户
        int fd_nums=epoll_wait(epollfd,events,1000,-1);
        //接收信息
        for(int i=0;i<fd_nums;i++)
        {
            int fd=events[i].data.fd;
            if(this->sock_account.find(fd)!=this->sock_account.end())
            {
                cout<<"消息套接字"<<endl;
                this->recv_message(fd);
                if(this->active_sock.find(fd)!=this->active_sock.end())
                this->handle_message(fd,need_handle_ccount);
            }
            else
            {
                //处理文件fd
                this->dele_unactive(fd);
            }
        }
        //处理need_handle_ccount
        for(int i=0;i<need_handle_ccount.size();i++)
        {
            this->send_message(need_handle_ccount[i]);
        }
    }
}

//检测客户——redis信息列表是否存在数据
bool server::check_redis_list(string account)
{
    if(this->redismanager.check_key_exsits(account)==1)
    {
        return true;
    }
    return false;
}

//设置无阻塞套接字
void server::set_nonblock(int fd)
{
    int flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

//新连接处理
void server::newconnect()
{
    int clientsocket=accept(this->listen_socket,NULL,NULL);
    if(clientsocket<0)
    {
        cout<<"accept failed"<<endl;
        return ;
    }
    uint32_t length;
    //读取长度
    if (recv(clientsocket, &length, sizeof(length), MSG_WAITALL) != sizeof(length)) {
        cerr<<"Failed to read message length"<<endl;
    }
    length = ntohl(length);
    //设置无阻塞
    this->set_nonblock(clientsocket);
    // 3. 读取消息内容（接收用户账号）
    std::vector<char> buffer(length);
    if (recv(clientsocket, buffer.data(), length, MSG_WAITALL) != length) {
        cerr<<"Failed to read message content"<<endl;
    }
    string account=string(buffer.data(),length);
    if(this->account_sock.find(account)!=this->account_sock.end())
    {
        this->accountfd_sock.emplace(account,clientsocket);
        this->sock_accountfd.emplace(clientsocket,account);
        this->active_sock.emplace(clientsocket);
        cout<<account<<":"<<clientsocket<<"文件套接字连接成功"<<endl;
        cout<<this->sock_accountfd[clientsocket]<<endl;
        cout<<this->accountfd_sock[account]<<endl;;
    }
    else
    {
        message_state temp;
        this->account_sock.emplace(account,clientsocket);
        this->sock_account.emplace(clientsocket,account);
        this->active_sock.emplace(clientsocket);
        this->save_message.emplace(account,temp);
        cout<<account<<":"<<clientsocket<<"消息套接字连接成功"<<endl;
        cout<<this->sock_account[clientsocket]<<endl;
        cout<<this->account_sock[account]<<endl;
    }
    this->organize_fd(clientsocket);
}


//接收数据
void server::recv_message(int fd)
{
    string buffer;
    int rev_length;
    string account=this->sock_account[fd];
    while(true)
    {
        char buff[1024];
        rev_length=recv(fd,buff,1024,0);
        if(rev_length>0)
        {
            buffer.append(buff,rev_length);
        }
        else if(rev_length==0)
        {
            this->dele_unactive(fd);
            break;
        }
        else
        {
            if (errno == EAGAIN || errno == EWOULDBLOCK) 
            {
                break;  // 数据已读完
            }
            else
            {
                this->dele_unactive(fd);
                break;
            }
        }
    }
    this->save_message[account].buff=this->save_message[account].buff+buffer;
    return ;
}

//处理接收数据
void server::handle_message(int fd,vector<string>&account_list)
{
    string account=this->sock_account[fd];
    while(this->save_message[account].buff.size()!=0)
    {
        if(this->save_message[account].state==0)
        {
            if(this->save_message[account].buff.size()>=4)
            {
                uint32_t length;
                memcpy(&length,this->save_message[account].buff.data(),4);
                length=ntohl(length);
                this->save_message[account].account_len=length;
                this->save_message[account].buff.erase(0,4);
                this->save_message[account].state=1;
                cout<<"账户长度"<<length<<endl;
            }
            else
            break;
        }
        else if(this->save_message[account].state==1)
        {
            if(this->save_message[account].buff.size()>=this->save_message[account].account_len)
            {
                int length=this->save_message[account].account_len;
                this->save_message[account].account=this->save_message[account].buff.substr(0,length);
                this->save_message[account].buff.erase(0,length);
                this->save_message[account].state=2;
                cout<<"账户"<<this->save_message[account].account<<endl;
            }
            else
            break;
        }
        else if(this->save_message[account].state==2)
        {
            if(this->save_message[account].buff.size()>=4)
            {
                uint32_t length;
                memcpy(&length,this->save_message[account].buff.data(),4);
                length=ntohl(length);
                this->save_message[account].message_len=length;
                this->save_message[account].buff.erase(0,4);
                this->save_message[account].state=3;
                cout<<"信息长度"<<length<<endl;
            }
            else
            break;
        }
        else if(this->save_message[account].state==3)
        {
            if(this->save_message[account].buff.size()>=this->save_message[account].message_len)
            {
                int length=this->save_message[account].message_len;
                this->save_message[account].message=this->save_message[account].buff.substr(0,length);
                this->save_message[account].buff.erase(0,length);
                this->save_message[account].state=0;
                cout<<"消息："<<this->save_message[account].message<<endl;
                //存入redis数据库持久化
                this->redismanager.lpush_message(this->save_message[account].account,this->save_message[account].message,account);
                account_list.push_back(this->save_message[account].account);
                this->save_message[account].account="";
                this->save_message[account].account_len=0;
                this->save_message[account].message_len=0;
                this->save_message[account].message="";
            }
            else
            break;
        }
    }
}

//发送数据
bool server::send_message( string recv_account)
{
    if(this->account_sock.find(recv_account)!=this->account_sock.end())
    {
        int fd=this->account_sock[recv_account];
        string message="";
        while((message=this->redismanager.get_message(recv_account))!="")
        {
            //设计账户长度统一为6个字节，分离账户和数据
            string send_account = message.substr(0, 6);
            cout<<"发送账户："<<send_account<<endl;
            //截取剩下全部数据
            string send_message=message.substr(6);
            cout<<"需要发送的信息"<<message<<endl;
            uint32_t send_length=htonl(send_account.size());
            //发送账户长度
            send_length=htonl(send_account.size());
            if(send(fd,&send_length,sizeof(send_length),0))
            {
                cout<<"发送长度成功"<<endl;
            }
            else
            {
                cout<<recv_account<<"socket失效"<<endl;
                this->dele_unactive(fd);
                return false;
            }
            //发送账户
            if(send(fd,(send_account).c_str(),(send_account).size(),0))
            {
                cout<<"发送账户成功"<<endl;
            }
            else
            {
                cout<<recv_account<<"socket失效"<<endl;
                this->dele_unactive(fd);
                return false;
            }
            //发送信息长度
            send_length=htonl(message.size());
            if(send(fd,&send_length,sizeof(send_length),0))
            {
                cout<<"发送长度成功"<<endl;
            }
            else
            {
                cout<<recv_account<<"socket失效"<<endl;
                this->dele_unactive(fd);
                return false;
            }
            //发送信息
            if(send(fd,send_message.c_str(),send_message.size(),0))
            {
                cout<<"发送信息成功"<<endl;
                this->upadte_time(fd);//更新时间
                this->redismanager.rpop_message(recv_account);//消除已发送出去的信息
            }
            else
            {
                cout<<recv_account<<"socket失效"<<endl;
                this->dele_unactive(fd);
                return false;
            }
        }
    }
    return true;
}

void server::dele_unactive(int fd)
{
    if(this->sock_account.find(fd)!=this->sock_account.end())
    {
        string account = this->sock_account[fd];
        cout << fd << " (" << account << ") 失去连接" << endl;
        // 清理所有相关映射
        this->account_sock.erase(account);  // account -> fd
        this->sock_account.erase(fd);      // fd -> account
        this->active_sock.erase(fd);       // 活跃 fd 集合
        this->save_message.erase(account); // 清理消息状态
        close(fd);
    }
    else
    {
        string account = this->sock_accountfd[fd];
        cout << fd << " (" << account << ") 文件套接字失去连接" << endl;
        // 清理文件套接字映射
        this->accountfd_sock.erase(account);
        this->sock_accountfd.erase(fd);
        this->active_sock.erase(fd);
        close(fd);
    }
}
void server::check_heart()
{
    //检测
    for(auto it=this->active_sock.begin();it!=this->active_sock.end();)
    {
        if(this->socket_time[*it]-chrono::steady_clock::now()>chrono::seconds(this->HEARTBEAT_INTERVAL))
        {
            this->dele_unactive(*it);
        }

    }
    this_thread::sleep_for(chrono::seconds(10));
}
//更新fd的时间
void server::upadte_time(int fd)
{
    this->socket_time[fd]=chrono::steady_clock::now();
}

//析构
server::~server()
{
    for(auto it=this->active_sock.begin();it!=this->active_sock.end();it=this->active_sock.begin())
    {
        shutdown(*it, SHUT_WR);
        this->active_sock.erase(it);
        close(*it);
    }
    shutdown(this->listen_socket, SHUT_WR);
    close(this->listen_socket);
    for(int i=0;i<4;i++)
    {
        close(this->epoll_fds[i]);
    }
}